package com.yupi.springbootinit.statemachine.processor;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yupi.springbootinit.mapper.QualityInspectionRecordMapper;
import com.yupi.springbootinit.model.entity.QualityInspectionRecord;
import com.yupi.springbootinit.statemachine.core.StateContext;
import com.yupi.springbootinit.statemachine.core.StateProcessor;
import com.yupi.springbootinit.statemachine.enums.QualityInspectionStateEnum;
import com.yupi.springbootinit.statemachine.enums.QualityInspectionEventEnum;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * 质检任务状态处理器
 * 处理质检任务状态转换的业务逻辑
 */
@Slf4j
@Component
public class QualityInspectionStateProcessor implements StateProcessor<QualityInspectionStateEnum, QualityInspectionEventEnum> {
    
    @Resource
    private QualityInspectionRecordMapper qualityInspectionRecordMapper;
    
    @Override
    public boolean beforeTransition(StateContext context) {
        log.info("质检任务状态转换前置处理: 实体[{}] {} -> {}", 
            context.getEntityId(),
            context.getCurrentState().getCode(),
            context.getTargetState().getCode());
        
        QualityInspectionStateEnum currentState = (QualityInspectionStateEnum) context.getCurrentState();
        QualityInspectionStateEnum targetState = (QualityInspectionStateEnum) context.getTargetState();
        
        switch (currentState) {
            case PENDING:
                return handlePendingToInProgress(context);
            case IN_PROGRESS:
                return handleInProgressTransition(context, targetState);
            case QUALIFIED:
                return handleQualifiedToCompleted(context);
            case UNQUALIFIED:
                return handleUnqualifiedToCompleted(context);
            default:
                return true;
        }
    }
    
    @Override
    public void afterTransition(StateContext context) {
        log.info("质检任务状态转换后置处理: 实体[{}] 转换完成", context.getEntityId());
        
        QualityInspectionStateEnum targetState = (QualityInspectionStateEnum) context.getTargetState();
        
        // 根据目标状态执行相应的后置处理
        switch (targetState) {
            case IN_PROGRESS:
                handleAfterStartInspection(context);
                break;
            case QUALIFIED:
                handleAfterQualified(context);
                break;
            case UNQUALIFIED:
                handleAfterUnqualified(context);
                break;
            case COMPLETED:
                handleAfterCompleted(context);
                break;
        }
        
        // 发送通知
        sendNotification(context);
    }
    
    @Override
    public void onTransitionError(StateContext context, Exception exception) {
        log.error("质检任务状态转换失败: 实体[{}] {} -> {}, 错误: {}", 
            context.getEntityId(),
            context.getCurrentState().getCode(),
            context.getTargetState().getCode(),
            exception.getMessage());
        
        // 记录错误并发送告警
        recordError(context, exception);
    }
    
    @Override
    public String getSupportedStateType() {
        return "QUALITY_INSPECTION";
    }
    
    /**
     * 处理待检验到检验中的转换
     */
    private boolean handlePendingToInProgress(StateContext context) {
        Long inspectionId = context.getEntityId();
        log.debug("检查质检任务[{}]开始条件", inspectionId);
        
        // 检查检验员是否可用
        if (!checkInspectorAvailable(context.getOperatorId())) {
            log.warn("质检任务[{}]检验员不可用", inspectionId);
            return false;
        }
        
        // 检查检验设备是否可用
        if (!checkInspectionEquipmentAvailable(inspectionId)) {
            log.warn("质检任务[{}]检验设备不可用", inspectionId);
            return false;
        }
        
        // 检查检验标准是否完整
        if (!checkInspectionStandardComplete(inspectionId)) {
            log.warn("质检任务[{}]检验标准不完整", inspectionId);
            return false;
        }
        
        return true;
    }
    
    /**
     * 处理检验中状态的转换
     */
    private boolean handleInProgressTransition(StateContext context, QualityInspectionStateEnum targetState) {
        Long inspectionId = context.getEntityId();
        
        if (targetState == QualityInspectionStateEnum.QUALIFIED) {
            // 转换到检验合格
            return validateQualifiedResult(inspectionId, context);
        } else if (targetState == QualityInspectionStateEnum.UNQUALIFIED) {
            // 转换到检验不合格
            return validateUnqualifiedResult(inspectionId, context);
        }
        
        return false;
    }
    
    /**
     * 处理检验合格到已完成的转换
     */
    private boolean handleQualifiedToCompleted(StateContext context) {
        Long inspectionId = context.getEntityId();
        log.debug("检查质检任务[{}]完成条件", inspectionId);
        
        // 检查检验报告是否已生成
        if (!checkInspectionReportGenerated(inspectionId)) {
            log.warn("质检任务[{}]检验报告未生成", inspectionId);
            return false;
        }
        
        return true;
    }
    
    /**
     * 处理检验不合格到已完成的转换
     */
    private boolean handleUnqualifiedToCompleted(StateContext context) {
        Long inspectionId = context.getEntityId();
        log.debug("检查质检任务[{}]不合格处理完成条件", inspectionId);
        
        // 检查不合格报告是否已生成
        if (!checkUnqualifiedReportGenerated(inspectionId)) {
            log.warn("质检任务[{}]不合格报告未生成", inspectionId);
            return false;
        }
        
        // 检查返工任务是否已创建
        if (!checkReworkTaskCreated(inspectionId)) {
            log.warn("质检任务[{}]返工任务未创建", inspectionId);
            return false;
        }
        
        return true;
    }
    
    /**
     * 开始检验后的处理
     */
    private void handleAfterStartInspection(StateContext context) {
        Long inspectionId = context.getEntityId();
        
        // 分配检验员
        assignInspector(inspectionId, context.getOperatorId());
        
        // 记录检验开始时间
        recordInspectionStartTime(inspectionId, context);
        
        // 预留检验设备
        reserveInspectionEquipment(inspectionId);
        
        log.info("质检任务[{}]已开始，检验员: {}", inspectionId, context.getOperatorName());
    }
    
    /**
     * 检验合格后的处理
     */
    private void handleAfterQualified(StateContext context) {
        Long inspectionId = context.getEntityId();
        
        // 记录检验结果
        recordInspectionResult(inspectionId, "QUALIFIED", context);
        
        // 生成合格证书
        generateQualificationCertificate(inspectionId);
        
        // 释放工序实例（允许继续下一工序）
        releaseProcessInstance(inspectionId);
        
        log.info("质检任务[{}]检验合格", inspectionId);
    }
    
    /**
     * 检验不合格后的处理
     */
    private void handleAfterUnqualified(StateContext context) {
        Long inspectionId = context.getEntityId();
        
        // 记录检验结果
        recordInspectionResult(inspectionId, "UNQUALIFIED", context);
        
        // 生成不合格报告
        generateUnqualifiedReport(inspectionId, context);
        
        // 创建返工任务
        createReworkTask(inspectionId);
        
        // 通知生产部返工
        notifyProductionForRework(inspectionId);
        
        log.info("质检任务[{}]检验不合格，已创建返工任务", inspectionId);
    }
    
    /**
     * 检验完成后的处理
     */
    private void handleAfterCompleted(StateContext context) {
        Long inspectionId = context.getEntityId();
        QualityInspectionStateEnum currentState = (QualityInspectionStateEnum) context.getCurrentState();
        
        // 记录检验完成时间
        recordInspectionCompleteTime(inspectionId, context);
        
        // 释放检验设备
        releaseInspectionEquipment(inspectionId);
        
        // 归档检验记录
        archiveInspectionRecord(inspectionId);
        
        if (currentState == QualityInspectionStateEnum.QUALIFIED) {
            // 合格完成：更新订单进度
            updateOrderProgress(inspectionId);
        } else if (currentState == QualityInspectionStateEnum.UNQUALIFIED) {
            // 不合格完成：等待返工
            waitForRework(inspectionId);
        }
        
        log.info("质检任务[{}]已完成", inspectionId);
    }
    
    /**
     * 发送通知
     */
    private void sendNotification(StateContext context) {
        QualityInspectionStateEnum targetState = (QualityInspectionStateEnum) context.getTargetState();
        Long inspectionId = context.getEntityId();
        
        switch (targetState) {
            case IN_PROGRESS:
                log.info("通知相关人员: 质检任务[{}]已开始检验", inspectionId);
                break;
            case QUALIFIED:
                log.info("通知生产部: 质检任务[{}]检验合格，可继续下一工序", inspectionId);
                log.info("通知项目部: 质检任务[{}]检验合格", inspectionId);
                break;
            case UNQUALIFIED:
                log.info("通知生产部: 质检任务[{}]检验不合格，需要返工", inspectionId);
                log.info("通知项目部: 质检任务[{}]检验不合格", inspectionId);
                break;
            case COMPLETED:
                log.info("通知相关人员: 质检任务[{}]已完成", inspectionId);
                break;
        }
    }
    
    // 以下为业务逻辑方法的简化实现
    
    private boolean checkInspectorAvailable(Long inspectorId) {
        // 检查检验员是否可用
        log.debug("检查检验员[{}]可用性", inspectorId);
        return true; // 简化实现
    }
    
    private boolean checkInspectionEquipmentAvailable(Long inspectionId) {
        // 检查检验设备是否可用
        log.debug("检查质检任务[{}]所需设备可用性", inspectionId);
        return true; // 简化实现
    }
    
    private boolean checkInspectionStandardComplete(Long inspectionId) {
        // 检查检验标准是否完整
        log.debug("检查质检任务[{}]检验标准完整性", inspectionId);
        return true; // 简化实现
    }
    
    private boolean validateQualifiedResult(Long inspectionId, StateContext context) {
        // 验证合格结果的有效性
        log.debug("验证质检任务[{}]合格结果", inspectionId);
        return true; // 简化实现
    }
    
    private boolean validateUnqualifiedResult(Long inspectionId, StateContext context) {
        // 验证不合格结果的有效性
        log.debug("验证质检任务[{}]不合格结果", inspectionId);
        return true; // 简化实现
    }
    
    private boolean checkInspectionReportGenerated(Long inspectionId) {
        // 检查检验报告是否已生成
        log.debug("检查质检任务[{}]检验报告生成状态", inspectionId);
        return true; // 简化实现
    }
    
    private boolean checkUnqualifiedReportGenerated(Long inspectionId) {
        // 检查不合格报告是否已生成
        log.debug("检查质检任务[{}]不合格报告生成状态", inspectionId);
        return true; // 简化实现
    }
    
    private boolean checkReworkTaskCreated(Long inspectionId) {
        // 检查返工任务是否已创建
        log.debug("检查质检任务[{}]返工任务创建状态", inspectionId);
        return true; // 简化实现
    }
    
    private void assignInspector(Long inspectionId, Long inspectorId) {
        // 分配检验员
        log.debug("为质检任务[{}]分配检验员[{}]", inspectionId, inspectorId);
    }
    
    private void recordInspectionStartTime(Long inspectionId, StateContext context) {
        // 记录检验开始时间
        log.debug("记录质检任务[{}]开始时间: {}", inspectionId, LocalDateTime.now());
        
        try {
            // 更新质检记录的开始检验时间
            UpdateWrapper<QualityInspectionRecord> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("step_id", inspectionId)
                .set("inspection_time", LocalDateTime.now())
                .set("inspector_id", context.getOperatorId())
                .set("inspector_name", context.getOperatorName())
                .set("update_time", LocalDateTime.now());
            
            qualityInspectionRecordMapper.update(null, updateWrapper);
        } catch (Exception e) {
            log.error("更新质检记录开始时间失败: inspectionId={}", inspectionId, e);
        }
    }
    
    private void reserveInspectionEquipment(Long inspectionId) {
        // 预留检验设备
        log.debug("为质检任务[{}]预留检验设备", inspectionId);
    }
    
    private void recordInspectionResult(Long inspectionId, String result, StateContext context) {
        // 记录检验结果
        log.debug("记录质检任务[{}]检验结果: {}", inspectionId, result);
        
        try {
            // 更新质检记录的检验结果
            UpdateWrapper<QualityInspectionRecord> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("step_id", inspectionId)
                .set("inspection_result", result)
                .set("update_time", LocalDateTime.now());
            
            qualityInspectionRecordMapper.update(null, updateWrapper);
        } catch (Exception e) {
            log.error("更新质检记录检验结果失败: inspectionId={}", inspectionId, e);
        }
    }
    
    private void generateQualificationCertificate(Long inspectionId) {
        // 生成合格证书
        log.debug("为质检任务[{}]生成合格证书", inspectionId);
    }
    
    private void releaseProcessInstance(Long inspectionId) {
        // 释放工序实例，允许继续下一工序
        log.debug("释放质检任务[{}]关联的工序实例", inspectionId);
    }
    
    private void generateUnqualifiedReport(Long inspectionId, StateContext context) {
        // 生成不合格报告
        log.debug("为质检任务[{}]生成不合格报告", inspectionId);
    }
    
    private void createReworkTask(Long inspectionId) {
        // 创建返工任务
        log.debug("为质检任务[{}]创建返工任务", inspectionId);
    }
    
    private void notifyProductionForRework(Long inspectionId) {
        // 通知生产部返工
        log.debug("通知生产部质检任务[{}]需要返工", inspectionId);
    }
    
    private void recordInspectionCompleteTime(Long inspectionId, StateContext context) {
        // 记录检验完成时间
        log.debug("记录质检任务[{}]完成时间: {}", inspectionId, LocalDateTime.now());
        
        try {
            // 更新质检记录的完成时间（这里我们使用更新时间作为完成时间）
            UpdateWrapper<QualityInspectionRecord> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("step_id", inspectionId)
                .set("update_time", LocalDateTime.now());
            
            qualityInspectionRecordMapper.update(null, updateWrapper);
        } catch (Exception e) {
            log.error("更新质检记录完成时间失败: inspectionId={}", inspectionId, e);
        }
    }
    
    private void releaseInspectionEquipment(Long inspectionId) {
        // 释放检验设备
        log.debug("释放质检任务[{}]检验设备", inspectionId);
    }
    
    private void archiveInspectionRecord(Long inspectionId) {
        // 归档检验记录
        log.debug("归档质检任务[{}]检验记录", inspectionId);
    }
    
    private void updateOrderProgress(Long inspectionId) {
        // 更新订单进度
        log.debug("更新质检任务[{}]关联订单进度", inspectionId);
    }
    
    private void waitForRework(Long inspectionId) {
        // 等待返工
        log.debug("质检任务[{}]等待返工完成", inspectionId);
    }
    
    private void recordError(StateContext context, Exception exception) {
        // 记录错误信息
        log.error("质检任务[{}]状态转换错误: {}", context.getEntityId(), exception.getMessage());
    }
}